using System;
using System.Text;
using System.Reflection;
using System.IO;
using MushManager.DAL;

namespace ScriptGen
{

	public class AssemblyParser
	{
		StringBuilder sb = new StringBuilder();
	
		public void ParseAssembly(Assembly assembly)
		{
			Type[] types = assembly.GetTypes();
			
			foreach(Type type in types)
			{
				if (type.IsClass)
				{
					DataTableAttribute[] dataTable = (DataTableAttribute[])type.GetCustomAttributes(typeof(DataTableAttribute), true);
				
					if (dataTable.Length > 0)
					{
						Console.WriteLine("Found class '{0}'", type.ToString());
						ParseClass(type, dataTable[0]);
						
						Console.WriteLine("");
					}
				}
			}
		}
		
		
		void ParseClass(Type type, DataTableAttribute dataTable)
		{
			PropertyInfo[] properties = type.GetProperties();
			
			sb.AppendFormat("\nCREATE TABLE [dbo].[{0}] (\n", dataTable.TableName);			
			
			// gets the key field
			foreach (PropertyInfo property in properties)
			{
				KeyFieldAttribute[] key = (KeyFieldAttribute[])property.GetCustomAttributes(typeof(KeyFieldAttribute), true);
				
				if (key.Length > 0)
				{
					Console.WriteLine("Key = " + property.Name + " type is " + property.PropertyType);
					sb.AppendFormat("\t[{0}] [int] IDENTITY (1, 1) PRIMARY KEY NOT NULL,\n", key[0].ColumnName);
					break;
				}
			}

			foreach (PropertyInfo property in properties)
			{
				ForeignKeyFieldAttribute[] foreignKeys = (ForeignKeyFieldAttribute[])property.GetCustomAttributes(typeof(ForeignKeyFieldAttribute), true);

				if (foreignKeys.Length > 0)
				{
					for (int i = 0; i < foreignKeys.Length; i++)
					{
						Console.WriteLine("ForeignKey = " + property.Name + " type is " + property.PropertyType);
						sb.AppendFormat("\t[{0}] [int] FOREIGN KEY([{0}]) REFERENCES [{1}]([{2}]) {3},\n", foreignKeys[0].ColumnName, foreignKeys[0].PKTable, foreignKeys[0].PKColumn, foreignKeys[0].Required == true ? "NOT NULL" : "NULL" );
					}
				}
			}
			
			// gets the other fields
			foreach (PropertyInfo property in properties)
			{
				DataFieldAttribute[] field = (DataFieldAttribute[])property.GetCustomAttributes(typeof(DataFieldAttribute), true);

				if (field.Length > 0)
				{
					Console.WriteLine("Property " + property.Name + " [" + property.PropertyType + "] maps to column [" + field[0].ColumnName + "]");
					if (property.PropertyType != typeof(System.String))
					{
						string columnType = "int";

						if (property.PropertyType == typeof(DateTime))
						{
							columnType = "datetime";
						}
						else if (property.PropertyType == typeof(Decimal))
						{
							columnType = "money";
						}

						sb.AppendFormat("\t[{0}] [{1}] {2},\n", field[0].ColumnName, columnType, field[0].Required == true ? "NOT NULL" : "NULL");
					}
					else
					{
						DataFieldAttribute dataField = field[0] as DataFieldAttribute;
						if (dataField != null)
						{
							sb.AppendFormat("\t[{0}] [varchar] ({1}) {2},\n", dataField.ColumnName, dataField.Size, dataField.Required == true ? "NOT NULL" : "NULL");
						}
					}
				}
			}
			
			
			sb.Remove(sb.Length - 2, 2);
			sb.AppendFormat("\n) ON [PRIMARY]\nGO\n");
		}	
		
		public string SQLScript
		{
			get { return sb.ToString(); }
		}		
	}
	

	public class App
	{
		public static void Main(string[] args)
		{
      Assembly assembly = null;
			
			try
			{
				//assembly = Assembly.LoadFrom(args[0]);
        assembly = Assembly.LoadFrom("MM.dll");
			}
			catch (Exception e)
			{
				Console.WriteLine("Failed to load assembly [" + args[0] + "]");
				Console.WriteLine(e.Message);
			}
	
			if (assembly != null)
			{
				AssemblyParser parser = new AssemblyParser();
				parser.ParseAssembly(assembly);

				// this code should be redone
				// it's now handling IO exceptions.
				FileStream fs = new FileStream("genScript.sql", FileMode.Create);
				StreamWriter writer = new StreamWriter(fs);

				writer.Write(parser.SQLScript);

				writer.Close();
				fs.Close();		
				
				Console.WriteLine("SQL script created [genScript.sql]");
				Console.Read();
			}
		}
	}
}